import { _decorator, AssetManager, instantiate, Layers, Node, Prefab, Size, UITransform, Widget } from "cc";
import BaseView from "./BaseView";
import { IBaseController } from "./BaseController";
import { IControllerInstance } from "db://assets/pkg-export/fairygui/FairyGUIView";

const { disallowMultiple } = _decorator;

export class ScriptView extends BaseView {
    public static preloadUI? (bundleName: string, complete: (result: Prefab|boolean) => void, onProgress?: (finish: number, total: number, item: AssetManager.RequestItem) => void): void;

    public static createUINode(parent: Node, prefab: Prefab|boolean): Node {
        const parentTransform = parent.getComponent(UITransform);
        const size = parentTransform && parentTransform.contentSize || new Size(100, 100);

        const root = this.createUIRoot(prefab);
        root.active = false;
        root.layer = Layers.Enum.UI_2D;
        const rootTrans = root.getComponent(UITransform) || root.addComponent(UITransform);
        rootTrans.setContentSize(size);

        if (!root.getComponent(Widget)) {
            const widget = root.addComponent(Widget);
            widget.isAlignLeft = widget.isAlignRight = widget.isAlignTop = widget.isAlignBottom = true;
            widget.left = widget.right = widget.top = widget.bottom = 0;
        }

        const ui = root.addComponent(this);
        ui.onUICreate(root, prefab);

        return root;
    }

    protected static createUIRoot(prefab: Prefab|boolean): Node {
        if (prefab instanceof Prefab) {
            return instantiate(prefab);
        } else {
            return new Node();
        }
    }

    protected onUICreate(root: Node, prefab: Prefab|boolean): void {
    }
}

export function ScriptViewBind<C, T extends { [key in string]: any }>(Controller: IBaseController<C, T>) {
    @disallowMultiple()
    class BindController extends ScriptView {
        protected get controller() {
            return Controller ? Controller.inst as any as IControllerInstance<C, T> : null;
        }
    }
    return BindController
}